using System;
using System.Collections.Generic;
using UnityEngine;

public class CustomisationConfig : ScriptableObject
{
	public enum ShadingType
	{
		Ambient = 0,
		Normal = 1
	}

	public enum PlayerType
	{
		Human = 0,
		AI = 1
	}

	public enum ModelNameEnum
	{
		Shoes001 = 0,
		Pants001 = 1,
		Shirt001 = 2,
		Eyes001 = 3,
		Hair_Bottom_001 = 4,
		Body001 = 5,
		Eyebrows001 = 6,
		Hair_Bottom_002 = 7,
		Face001 = 8,
		Hair_Bottom_005 = 9,
		Hair_Bottom_003 = 10,
		Hair_Bottom_004 = 11,
		Hair_Top_001 = 12,
		Hair_Top_003 = 13,
		Hair_Top_004 = 14,
		Retina001 = 15,
		Eyelashes001 = 16,
		Hair_Top_006 = 17,
		Hair_Bottom_006 = 18,
		Hair007 = 19,
		Hair_Top_002 = 20,
		Hair_Top_005 = 21,
		FACE001 = 22,
		SHOES002 = 23,
		F_BODY_001 = 24,
		F_HEAD_001 = 25,
		F_PANTS_001 = 26,
		F_SHIRT_001 = 27,
		F_SHOES = 28,
		F_EYES_001 = 29,
		F_EYEBROWS_001 = 30,
		F_EYELASHES_001 = 31,
		F_HAIR_TOP_001 = 32,
		F_HAIR_BOTTOM_001 = 33,
		F_PUPIL_001 = 34,
		F_HAIR_TOP_003 = 35,
		F_HAIR_BOTTOM_003 = 36,
		F_HAIR_TOP_002 = 37,
		RUBBER001 = 38
	}

	[Serializable]
	public class LookProperty
	{
		public string lookPropertyName;

		public ModelNameEnum modelName;

		public ShaderDefinitionName shaderName;

		public string mainTexture;

		public string colourTexture;

		public string normalTexture;

		public Color colourRed;

		public Color colourGreen;

		public Color colourBlue;

		[Range(0f, 3f)]
		public float highlightPower;

		[Range(0f, 3f)]
		public float highlightPowerRed;

		[Range(0f, 3f)]
		public float highlightPowerGreen;

		[Range(0f, 3f)]
		public float highlightPowerBlue;

		[Range(0f, 1f)]
		public float specularFocus = 0.5f;

		[Range(0f, 10f)]
		public float specularStrength = 0.05f;

		[Range(0f, 1f)]
		public float rimFocus = 0.5f;

		[Range(0f, 1f)]
		public float rimStrength = 0.5f;

		public LookProperty Clone()
		{
			LookProperty lookProperty = new LookProperty();
			lookProperty.lookPropertyName = lookPropertyName;
			lookProperty.modelName = modelName;
			lookProperty.shaderName = shaderName;
			lookProperty.mainTexture = mainTexture;
			lookProperty.colourTexture = colourTexture;
			lookProperty.normalTexture = normalTexture;
			lookProperty.colourRed = colourRed;
			lookProperty.colourGreen = colourGreen;
			lookProperty.colourBlue = colourBlue;
			lookProperty.highlightPower = highlightPower;
			lookProperty.highlightPowerRed = highlightPowerRed;
			lookProperty.highlightPowerGreen = highlightPowerGreen;
			lookProperty.highlightPowerBlue = highlightPowerBlue;
			lookProperty.specularFocus = specularFocus;
			lookProperty.specularStrength = specularStrength;
			lookProperty.rimFocus = rimFocus;
			lookProperty.rimStrength = rimStrength;
			return lookProperty;
		}

		public void ApplyLook(LookSetType type, PersonaModel personaModel, ShaderUseType useType)
		{
			ShaderUseDefinition shaderDefinition = instance.GetShaderDefinition(shaderName, useType);
			ShaderConfig shaderConfig = instance.GetShaderConfig(shaderDefinition.shaderConfig);
			personaModel.ApplyModelLook(type, this, shaderConfig);
		}
	}

	[Serializable]
	public class Condition
	{
		public bool checkGender;

		public Persona.Gender gender;

		public Condition Clone()
		{
			Condition condition = new Condition();
			condition.checkGender = checkGender;
			condition.gender = gender;
			return condition;
		}

		public bool IsConditionPassed(Persona.Gender gender)
		{
			if (!checkGender)
			{
				return true;
			}
			if (this.gender == gender)
			{
				return true;
			}
			return false;
		}

		public bool IsConditionPassed(Persona persona)
		{
			return IsConditionPassed(persona.gender);
		}
	}

	[Serializable]
	public class LookAction
	{
		public bool changeGender;

		public Persona.Gender gender;

		public LookAction Clone()
		{
			LookAction lookAction = new LookAction();
			lookAction.changeGender = changeGender;
			lookAction.gender = gender;
			return lookAction;
		}
	}

	[Serializable]
	public class Look
	{
		public string lookName;

		public int price;

		public CurrencyType currency;

		public List<LookProperty> lookProperties = new List<LookProperty>();

		public Condition condition;

		public LookAction action;

		public LookSetType type;

		public bool isOwned
		{
			get
			{
				return PlayerInventory.instance.isOwned(lookName);
			}
		}

		public bool IsAvailable(Persona persona)
		{
			return condition.IsConditionPassed(persona);
		}

		public void ApplyLook(PersonaModel personaModel, ShaderUseType useType)
		{
			personaModel.ClearPartsForType(type);
			foreach (LookProperty lookProperty in lookProperties)
			{
				lookProperty.ApplyLook(type, personaModel, useType);
			}
		}

		public Look Clone()
		{
			Look look = new Look();
			look.lookName = lookName;
			look.price = price;
			look.currency = currency;
			look.lookProperties = new List<LookProperty>();
			foreach (LookProperty lookProperty in lookProperties)
			{
				look.lookProperties.Add(lookProperty.Clone());
			}
			look.condition = condition.Clone();
			look.action = action.Clone();
			look.type = type;
			return look;
		}
	}

	[Serializable]
	public class LookSet
	{
		public string lookSetName;

		public List<Look> looks = new List<Look>();

		public LookSetType type;

		public LookSet Clone()
		{
			LookSet lookSet = new LookSet();
			lookSet.lookSetName = lookSetName;
			lookSet.looks = new List<Look>();
			foreach (Look look in looks)
			{
				lookSet.looks.Add(look.Clone());
			}
			lookSet.type = type;
			return lookSet;
		}

		public Look GetDefaultLookForPersona(Persona persona)
		{
			foreach (Look look in looks)
			{
				if (look.IsAvailable(persona) && look.price <= 0)
				{
					return look;
				}
			}
			return null;
		}

		public List<Look> GetLooksApplicableForPersona(Persona persona)
		{
			List<Look> list = new List<Look>();
			foreach (Look look in looks)
			{
				if (look.IsAvailable(persona))
				{
					list.Add(look);
				}
			}
			return list;
		}

		public Look GetLookByName(string name, Persona.Gender gender)
		{
			name = name.Replace("Female", string.Empty);
			if (gender == Persona.Gender.Female)
			{
				name += "Female";
			}
			foreach (Look look in looks)
			{
				if (look.lookName == name && look.condition.IsConditionPassed(gender))
				{
					return look;
				}
			}
			return null;
		}

		public int GetLookIndexByName(string name, Persona.Gender gender)
		{
			name = name.Replace("Female", string.Empty);
			if (gender == Persona.Gender.Female)
			{
				name += "Female";
			}
			for (int i = 0; i < looks.Count; i++)
			{
				if (looks[i].lookName == name && looks[i].condition.IsConditionPassed(gender))
				{
					return i;
				}
			}
			return -1;
		}
	}

	public enum LookSetType
	{
		Face = 0,
		Skin = 1,
		Hair = 2,
		Eyes = 3,
		Shirt = 4,
		Pants = 5,
		Shoes = 6,
		Gender = 7,
		Racket = 8
	}

	[Serializable]
	public class BodyPartModelDefinition
	{
		public LookSetType type;

		public List<string> modelNames = new List<string>();
	}

	public enum ShaderDefinitionName
	{
		SkinTypeShader = 0,
		HeadTypeShader = 1,
		HairTopTypeShader = 2,
		HairBottomTypeShader = 3,
		PantsTypeShader = 4,
		ShirtTypeShader = 5,
		ShoesTypeShader = 6,
		HairTopHighlightsTypeShader = 7,
		HairBottomHighlightsTypeShader = 8,
		RacketTypeShader = 9
	}

	[Serializable]
	public class ShaderDefinitions
	{
		public ShaderDefinitionName shaderDefName;

		public List<ShaderUseDefinition> useDefinitions = new List<ShaderUseDefinition>();
	}

	public enum ShaderUseType
	{
		MatchHumanPlayer = 0,
		MatchAIPlayer = 1,
		MenuConfigPlayer = 2,
		MatchHumanPlayerAmbient = 3,
		MatchAIPlyerAmbient = 4
	}

	[Serializable]
	public class ShaderUseDefinition
	{
		public ShaderUseType useType;

		public ShaderConfigType shaderConfig;
	}

	public enum ShaderConfigType
	{
		ColorMaterialShader = 0,
		MobileUnlitShader = 1,
		UnlitTransparentShader = 2,
		DiffuseWrapTransparent = 3,
		DiffuseWrapTransparentTransparent = 4,
		DiffuseWrapTransparentSingleColour = 5,
		HairShader = 6,
		DiffuseWrapTransparentHairShader = 7,
		HairShaderTransparent = 8,
		DiffuseWrapTransparentHairShaderTransparent = 9,
		ColorMaterialSpecular = 10,
		ColorMaterialSpecularScreenCutout = 11,
		SkinMaterial = 12,
		SkinMaterialScreenCutout = 13,
		HairShaderHighlights = 14,
		DiffuseWrapTransparentHairShaderHighlights = 15,
		HairShaderTransparentHighlights = 16,
		DiffuseWrapTransparentHairShaderTransparentHighlights = 17,
		SkinMaterialAmbient = 18,
		SkinMaterialAmbientScreenCutout = 19,
		ColorMaterialAmbient = 20,
		ColorMaterialAmbientTransparent = 21,
		RacketRubberMaterialSpecular = 22,
		SkinMaterialAmbientLight = 23,
		ColorMaterialAmbientLight = 24,
		HairShaderAmbientLight = 25,
		HairShaderTransparentAmbientLight = 26
	}

	[Serializable]
	public class ShaderConfig
	{
		[Serializable]
		public class PropertyConstant
		{
			public enum Type
			{
				FloatType = 0,
				ColorType = 1
			}

			public string name;

			public Type type;

			public float floatValue;

			public Color colorValue;

			public void ApplyOn(Material material)
			{
				switch (type)
				{
				case Type.FloatType:
					material.SetFloat(name, floatValue);
					break;
				case Type.ColorType:
					material.SetColor(name, colorValue);
					break;
				}
			}
		}

		public ShaderConfigType myType;

		public Shader shaderName;

		public string mainTexturePropName;

		public string secondTexturePropName;

		public string normalTexturePropName;

		public string colourRedPropName;

		public string colourGreenPropName;

		public string colourBluePropName;

		public string highlightPowerPropName;

		public string highlightPowerRedPropName;

		public string highlightPowerGreenPropName;

		public string highlightPowerBluePropName;

		public string specularFocusPropName;

		public string specularStrengthPropName;

		public string rimFocusPropName;

		public string rimStrengthPropName;

		public bool shouldUpdateWithBallPos;

		public bool shouldUpdateWithAmbient;

		public List<PropertyConstant> constants = new List<PropertyConstant>();

		public virtual void InitMaterial(Material mat)
		{
		}

		public virtual bool ShouldUpdateWithBallPos()
		{
			return shouldUpdateWithBallPos;
		}

		public void ApplyOn(Material material)
		{
			foreach (PropertyConstant constant in constants)
			{
				constant.ApplyOn(material);
			}
		}
	}

	private static CustomisationConfig instance_;

	public List<ShaderDefinitions> shaderDefinitions = new List<ShaderDefinitions>();

	public List<ShaderConfig> shaderConfigs = new List<ShaderConfig>();

	public List<BodyPartModelDefinition> modelDefinitions = new List<BodyPartModelDefinition>();

	public List<LookSet> lookSets = new List<LookSet>();

	public static CustomisationConfig instance
	{
		get
		{
			if (instance_ == null)
			{
				instance_ = Resources.Load("CharacterCustomisation/CustomisationConfig", typeof(CustomisationConfig)) as CustomisationConfig;
			}
			return instance_;
		}
	}

	public static ShaderUseType MatchShaderUseType(ShadingType shadingType, PlayerType playerType)
	{
		if (shadingType == ShadingType.Ambient)
		{
			if (playerType == PlayerType.Human)
			{
				return ShaderUseType.MatchHumanPlayerAmbient;
			}
			return ShaderUseType.MatchAIPlyerAmbient;
		}
		if (playerType == PlayerType.Human)
		{
			return ShaderUseType.MatchHumanPlayer;
		}
		return ShaderUseType.MatchAIPlayer;
	}

	public ShaderUseDefinition GetShaderDefinition(ShaderDefinitionName definitionsName, ShaderUseType useType)
	{
		ShaderDefinitions shaderDefinitions = null;
		foreach (ShaderDefinitions shaderDefinition in this.shaderDefinitions)
		{
			if (shaderDefinition.shaderDefName == definitionsName)
			{
				shaderDefinitions = shaderDefinition;
				break;
			}
		}
		if (shaderDefinitions == null)
		{
			return null;
		}
		foreach (ShaderUseDefinition useDefinition in shaderDefinitions.useDefinitions)
		{
			if (useDefinition.useType == useType)
			{
				return useDefinition;
			}
		}
		return null;
	}

	public ShaderConfig GetShaderConfig(ShaderConfigType configType)
	{
		foreach (ShaderConfig shaderConfig in shaderConfigs)
		{
			if (shaderConfig.myType == configType)
			{
				return shaderConfig;
			}
		}
		return null;
	}

	public List<string> GetNameForType(LookSetType type)
	{
		foreach (BodyPartModelDefinition modelDefinition in modelDefinitions)
		{
			if (modelDefinition.type == type)
			{
				return modelDefinition.modelNames;
			}
		}
		return null;
	}

	public LookSet GetLookSetForType(LookSetType type)
	{
		foreach (LookSet lookSet in lookSets)
		{
			if (lookSet.type == type)
			{
				return lookSet;
			}
		}
		return null;
	}

	public Look GetLookForTypeAndName(LookSetType type, string name)
	{
		foreach (LookSet lookSet in lookSets)
		{
			if (lookSet.type != type)
			{
				continue;
			}
			foreach (Look look in lookSet.looks)
			{
				if (look.lookName == name)
				{
					return look;
				}
			}
		}
		return null;
	}

	public int GetLookIndex(LookSetType type, Look selectedLook)
	{
		LookSet lookSetForType = GetLookSetForType(type);
		return lookSetForType.looks.IndexOf(selectedLook);
	}

	public void ApplyLooksForPersona(PersonaModel personaModel, Persona persona, ShaderUseType useType)
	{
		foreach (LookSetType value in Enum.GetValues(typeof(LookSetType)))
		{
			Look lookForType = persona.GetLookForType(value);
			if (lookForType != null)
			{
				lookForType.ApplyLook(personaModel, useType);
			}
		}
	}
}
